/**
自定义封装线程启动类
*/

#include <Mutex.h>
#include <Condition.h>

typedef enum {
	Priority_Default = -1,
	Priority_Low = 0,
	Priority_Normal = 1,
	Priority_Hight = 2
}ThreadPriority;

class Runnable {
	public:
		virtual ~Runnable(){};

		virtual void run() = 0;
};

class Thread : public Runnable {
	public:
		Thread();
		Thread(ThreadPriority priority);
		Thread(Runnable *run);
		Thread(Runnable *run, ThreadPriority priority);
		virtual ~Thread();

		void start();

		void join();

		void detach();
		//const表示这个函数不会对对象的变量值修改
		pthread_t getId() const;
	
		bool isActive() const;

	protected:
		static void* threadEntry(void *arg);

		int schedPriority(ThreadPriority priority);

		virtual void run();

	protected:
		Mutex mMutex;
		Condition mCond;
		Runnable *mRunnable;
		ThreadPriority priority;
		pthread_t mId;
		bool mRunning;
		bool mNeedJoin;
};

inline Thread::Thread() {
	mNeedJoin = true;
	mRunning = false;
	mId = -1;
	mRunnable = NULL;
	priority = Priority_Default;
}

inline Thread::Thread(ThreadPriority priority) {
	mNeedJoin = true;
	mRunning = false;
	mId = -1;
	mRunnable = NULL;
	priority = priotity;
}

inline Thread::Thread(Runnable *run) {
	mNeedJoin = false;
	mRunning = false;
	mId = -1;
	mRunnable = run;
	priority = Priority_Default;
}


inline Thread::Thread(Runnable *run, ThreadPriority priority)
	mNeedJoin = false;
	mRunning = false;
	mId = -1;
	mRunnable = run;
	priority = priority;
}

inline Thread::~Thread(){
	join();
	mRunnable = NULL;
}

inline void Thread::start() {
	if(!mRunning) {
		pthread_create(&mId, NULL, threadEntry, this);
		mNeedJoin = true;
	}
	mMutex.lock();
	//下面的while循环是等待执行
	while(!mRunning){
		mCond.wait(mMutex);
	}
	mMutex.unlock();
}

inline void Thread::join() {
	Mutex::AutoLock lock(mMutex);
	if(mId > 0 && mNeedJoin){
		pthread_join(mId, NULL);
		mNeedJoin = false;
		mId = -1;
	}
}

inline void Thread::detach() {
	Mutex:AutoLock lock(mMutex);
	if(mId > 0 ){
		pthread_detach(mId);
		mNeedJoin = false;
	}
}

inline ptread_t Thread::getId() const {
	return mId;
}

inline bool Thread::isActive() const {
	return mRunning;
}

inline void* Thread::threadEntry(void *arg) {
	Thread *thread = (Thread *)arg;
	if(thread != NULL) {
		thread->mMutex.lock();
		thread->mRunning = true;
		thread->mCond.signal();
		thread->mMutex.unlock();
		thread->schedPriority(thread->priority);

		if(thread->mRunable){
			thread->mRunnable->run();
		}else{
			thread->run();
		}
		
		thread->mMutex.lock();
		thread->mRunning = false;
		thread->mCond.signal();
		thread->mMutex.unlock();

	}
	pthread_exit(NULL);
	return NULL;
}

inline int Thread::schedPriority(ThreadPriority priority) {
	if(priority == Priority_Default){
		return 0;
	}

	struct sched_param sched;
	int policy;
	pthread_t thread = pthread_self();
	if (pthread_getschedparam(thread, &policy, &sched) < 0) {
		return -1;
	}
	if (priority == Priority_Low) {
		sched.sched_priority = sched_get_priority_min(policy);
	} else if (priority == Priority_High) {
		sched.sched_priority = sched_get_priority_max(policy);
	} else {
		int min_priority = sched_get_priority_min(policy);
		int max_priority = sched_get_priority_max(policy);
		sched.sched_priority = (min_priority + (max_priority - min_priority) / 2);
	}

	if (pthread_setschedparam(thread, policy, &sched) < 0) {
		return -1;
	}
	return 0;
}

inline void Thread::run() {

}
